import sys
import os
import uuid
import time
from PySide6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                             QHBoxLayout, QLineEdit, QPushButton, QLabel, 
                             QComboBox, QFileDialog, QMessageBox, QProgressBar,
                             QFrame, QTabWidget, QScrollArea, QSizePolicy)
from PySide6.QtCore import Qt, QThread, Signal, QMutex, QSize, QTimer
from PySide6.QtGui import QPixmap, QFont, QPalette, QColor, QIcon
import yt_dlp
from PIL import Image, ImageDraw
import requests
from io import BytesIO
from enum import Enum

class TaskStatus(Enum):
    WAITING = 0
    DOWNLOADING = 1
    PAUSED = 2
    COMPLETED = 3
    ERROR = 4
    CANCELED = 5

class TaskCreationThread(QThread):
    """用于创建下载任务的线程，减少UI卡顿"""
    task_created = Signal(str, object, object)  # 任务ID、下载线程对象、任务项UI对象
    
    def __init__(self, url, format_id, output_path, video_info, download_manager):
        super().__init__()
        self.url = url
        self.format_id = format_id
        self.output_path = output_path
        self.video_info = video_info
        self.download_manager = download_manager
        
    def run(self):
        # 创建下载线程
        download_thread = DownloadThread(
            self.url,
            self.format_id,
            self.output_path,
            self.video_info
        )
        
        # 添加到下载管理器
        task_id = self.download_manager.add_task(download_thread, self.video_info)
        
        # 创建任务UI
        task_item = DownloadTaskItem(task_id, self.video_info, download_thread)
        
        # 发送信号，让主线程完成UI更新
        self.task_created.emit(task_id, download_thread, task_item)

class FetchInfoThread(QThread):
    finished = Signal(dict)
    error = Signal(str)
    progress = Signal(str)
    thumbnail_ready = Signal(QPixmap)  # 新增信号用于传递处理好的缩略图

    def __init__(self, url):
        super().__init__()
        self.url = url

    def run(self):
        try:
            self.progress.emit('正在获取视频信息...')
            with yt_dlp.YoutubeDL() as ydl:
                info = ydl.extract_info(self.url, download=False)
                
                # 在线程中处理缩略图
                thumbnail_url = info.get('thumbnail')
                if thumbnail_url:
                    try:
                        self.progress.emit('正在加载缩略图...')
                        response = requests.get(thumbnail_url)
                        img = Image.open(BytesIO(response.content))
                        img = img.resize((240, 135), Image.Resampling.LANCZOS)
                        
                        # 添加圆角
                        mask = Image.new('L', img.size, 0)
                        draw = ImageDraw.Draw(mask)
                        draw.rounded_rectangle([(0, 0), img.size], radius=8, fill=255)
                        output = Image.new('RGBA', img.size, (0, 0, 0, 0))
                        output.paste(img, mask=mask)
                        
                        # 保存并发送缩略图
                        temp_path = 'temp_thumbnail.png'
                        output.save(temp_path)
                        self.thumbnail_ready.emit(QPixmap(temp_path))
                    except Exception as e:
                        # 缩略图处理失败不影响整体流程
                        pass
                
                self.finished.emit(info)
        except Exception as e:
            self.error.emit(str(e))

class DownloadThread(QThread):
    progress = Signal(str, float, int)  # 消息、进度百分比、已下载字节数
    finished = Signal()
    error = Signal(str)
    status_changed = Signal(TaskStatus)

    def __init__(self, url, format_id, output_path, video_info=None):
        super().__init__()
        self.url = url
        self.format_id = format_id
        self.output_path = output_path
        self.video_info = video_info
        self.status = TaskStatus.WAITING
        self.pause_mutex = QMutex()
        self.paused = False
        self.canceled = False
        self.total_bytes = 0
        self.downloaded_bytes = 0
        self.filename = ""

    def run(self):
        try:
            self.status = TaskStatus.DOWNLOADING
            self.status_changed.emit(self.status)
            
            ydl_opts = {
                'format': self.format_id,
                'outtmpl': os.path.join(self.output_path, '%(title)s.%(ext)s'),
                'progress_hooks': [self.progress_hook],
            }
            
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                # 添加对暂停和取消的检查
                def check_stop():
                    if self.canceled:
                        return True
                    
                    self.pause_mutex.lock()
                    is_paused = self.paused
                    self.pause_mutex.unlock()
                    
                    if is_paused:
                        self.status = TaskStatus.PAUSED
                        self.status_changed.emit(self.status)
                        # 等待恢复
                        while True:
                            time.sleep(0.1)
                            self.pause_mutex.lock()
                            still_paused = self.paused
                            is_canceled = self.canceled
                            self.pause_mutex.unlock()
                            
                            if is_canceled:
                                return True
                            if not still_paused:
                                self.status = TaskStatus.DOWNLOADING
                                self.status_changed.emit(self.status)
                                break
                    return False
                
                # 重写yt-dlp的钩子函数
                original_hook = ydl._progress_hooks
                def custom_hook(d):
                    if check_stop():
                        raise Exception("Download canceled")
                    
                    if self.status == TaskStatus.DOWNLOADING:
                        for hook in original_hook:
                            hook(d)
                
                ydl._progress_hooks = [custom_hook]
                ydl.download([self.url])
            
            if not self.canceled:
                self.status = TaskStatus.COMPLETED
                self.status_changed.emit(self.status)
                self.finished.emit()
                
        except Exception as e:
            if self.canceled:
                self.status = TaskStatus.CANCELED
            else:
                self.status = TaskStatus.ERROR
            self.status_changed.emit(self.status)
            self.error.emit(str(e))

    def progress_hook(self, d):
        if d['status'] == 'downloading':
            try:
                filename = d.get('filename', '').split('/')[-1]
                if filename and not self.filename:
                    self.filename = filename
                    
                self.total_bytes = d.get('total_bytes', 0)
                if self.total_bytes == 0:
                    self.total_bytes = d.get('total_bytes_estimate', 0)
                    
                self.downloaded_bytes = d.get('downloaded_bytes', 0)
                
                if self.total_bytes > 0:
                    percentage = (self.downloaded_bytes / self.total_bytes) * 100
                    self.progress.emit(
                        f'下载进度: {percentage:.1f}%',
                        percentage,
                        self.downloaded_bytes
                    )
            except Exception as e:
                pass

    def pause(self):
        self.pause_mutex.lock()
        self.paused = True
        self.pause_mutex.unlock()

    def resume(self):
        self.pause_mutex.lock()
        self.paused = False
        self.pause_mutex.unlock()

    def cancel(self):
        self.pause_mutex.lock()
        self.canceled = True
        self.paused = False  # 如果是暂停状态，取消暂停以便线程能继续执行到取消检查
        self.pause_mutex.unlock()

    def get_status(self):
        return self.status

    def get_file_size(self):
        return self.total_bytes

class DownloadTaskItem(QFrame):
    task_canceled = Signal(str)  # 任务ID
    task_paused = Signal(str)
    task_resumed = Signal(str)
    
    def __init__(self, task_id, video_info, download_thread, parent=None):
        super().__init__(parent)
        self.task_id = task_id
        self.video_info = video_info
        self.download_thread = download_thread
        self.setupUI()
        
        # 连接信号
        self.download_thread.progress.connect(self.update_progress)
        self.download_thread.status_changed.connect(self.update_status)
        self.download_thread.finished.connect(self.on_download_finished)
        self.download_thread.error.connect(self.on_download_error)
    
    def setupUI(self):
        # 设置任务项样式
        self.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                margin: 5px;
                padding: 10px;
            }
            QPushButton {
                min-width: 80px;
                padding: 5px 10px;
            }
            QProgressBar {
                border: none;
                background-color: #E0E0E0;
                border-radius: 4px;
                text-align: center;
                height: 8px;
            }
            QProgressBar::chunk {
                background-color: #2196F3;
                border-radius: 4px;
            }
        """)
        
        main_layout = QVBoxLayout(self)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(10)
        
        # 上部分：缩略图和标题
        top_container = QHBoxLayout()
        top_container.setSpacing(10)
        
        # 缩略图
        self.thumbnail_label = QLabel()
        self.thumbnail_label.setFixedSize(120, 68)
        self.thumbnail_label.setStyleSheet("""
            QLabel {
                border: 1px solid #ddd;
                border-radius: 4px;
                background-color: #f0f0f0;
            }
        """)
        
        # 设置占位图片
        placeholder = QPixmap(120, 68)
        placeholder.fill(QColor("#f0f0f0"))
        self.thumbnail_label.setPixmap(placeholder)
        
        # 异步加载缩略图
        QTimer.singleShot(50, self.load_thumbnail_async)
        
        top_container.addWidget(self.thumbnail_label)
        
        # 标题和信息容器
        info_container = QVBoxLayout()
        info_container.setSpacing(5)
        
        # 视频标题
        self.title_label = QLabel(self.video_info.get('title', '未知视频') if self.video_info else '未知视频')
        self.title_label.setStyleSheet("font-weight: bold; font-size: 13px;")
        self.title_label.setWordWrap(True)
        info_container.addWidget(self.title_label)
        
        # 文件大小信息
        file_size = self.download_thread.get_file_size()
        size_text = self.format_size(file_size) if file_size > 0 else '大小未知'
        self.size_label = QLabel(f"大小: {size_text}")
        self.size_label.setStyleSheet("color: #666; font-size: 12px;")
        info_container.addWidget(self.size_label)
        
        # 状态信息
        self.status_label = QLabel("状态: 等待中")
        self.status_label.setStyleSheet("color: #666; font-size: 12px;")
        info_container.addWidget(self.status_label)
        
        top_container.addLayout(info_container, 1)
        main_layout.addLayout(top_container)
        
        # 进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        main_layout.addWidget(self.progress_bar)
        
        # 按钮容器
        button_container = QHBoxLayout()
        button_container.setSpacing(10)
        
        # 暂停/继续按钮
        self.pause_resume_btn = QPushButton("暂停")
        self.pause_resume_btn.clicked.connect(self.toggle_pause_resume)
        
        # 取消按钮
        self.cancel_btn = QPushButton("取消")
        self.cancel_btn.clicked.connect(self.cancel_download)
        self.cancel_btn.setStyleSheet("background-color: #F44336;")
        
        button_container.addStretch(1)
        button_container.addWidget(self.pause_resume_btn)
        button_container.addWidget(self.cancel_btn)
        
        main_layout.addLayout(button_container)
    
    def load_thumbnail_async(self):
        """异步加载缩略图"""
        class ThumbnailLoader(QThread):
            thumbnail_ready = Signal(QPixmap)
            
            def __init__(self, video_info, task_id):
                super().__init__()
                self.video_info = video_info
                self.task_id = task_id
                
            def run(self):
                if not self.video_info:
                    return
                    
                thumbnail_url = self.video_info.get('thumbnail')
                if not thumbnail_url:
                    return
                    
                try:
                    response = requests.get(thumbnail_url)
                    img = Image.open(BytesIO(response.content))
                    img = img.resize((120, 68), Image.Resampling.LANCZOS)
                    
                    # 添加圆角
                    mask = Image.new('L', img.size, 0)
                    draw = ImageDraw.Draw(mask)
                    draw.rounded_rectangle([(0, 0), img.size], radius=4, fill=255)
                    
                    output = Image.new('RGBA', img.size, (0, 0, 0, 0))
                    output.paste(img, mask=mask)
                    
                    # 使用唯一文件名，避免冲突
                    task_thumbnail_path = f'temp_task_{self.task_id}.png'
                    output.save(task_thumbnail_path)
                    
                    # 发送信号
                    self.thumbnail_ready.emit(QPixmap(task_thumbnail_path))
                except Exception:
                    # 错误处理：失败时保持占位图
                    pass
        
        if self.video_info:
            # 创建并启动线程
            loader = ThumbnailLoader(self.video_info, self.task_id)
            
            # 连接信号
            loader.thumbnail_ready.connect(self.set_thumbnail)
            
            # 启动线程
            loader.start()
            
            # 保持引用防止被垃圾回收
            self._thumbnail_loader = loader
    
    def set_thumbnail(self, pixmap):
        """设置缩略图"""
        self.thumbnail_label.setPixmap(pixmap)
        
    def update_progress(self, message, percentage, downloaded_bytes):
        self.progress_bar.setValue(int(percentage))
        
        # 更新大小信息
        file_size = self.download_thread.get_file_size()
        if file_size > 0:
            size_text = f"{self.format_size(downloaded_bytes)} / {self.format_size(file_size)}"
            self.size_label.setText(f"大小: {size_text}")
    
    def update_status(self, status):
        status_texts = {
            TaskStatus.WAITING: "等待中",
            TaskStatus.DOWNLOADING: "下载中",
            TaskStatus.PAUSED: "已暂停",
            TaskStatus.COMPLETED: "已完成",
            TaskStatus.ERROR: "下载出错",
            TaskStatus.CANCELED: "已取消"
        }
        
        status_text = status_texts.get(status, "未知状态")
        self.status_label.setText(f"状态: {status_text}")
        
        # 更新按钮状态
        if status == TaskStatus.PAUSED:
            self.pause_resume_btn.setText("继续")
        elif status == TaskStatus.DOWNLOADING:
            self.pause_resume_btn.setText("暂停")
        
        # 禁用按钮（如果任务已完成、出错或取消）
        if status in [TaskStatus.COMPLETED, TaskStatus.ERROR, TaskStatus.CANCELED]:
            self.pause_resume_btn.setEnabled(False)
            self.cancel_btn.setEnabled(False)
    
    def on_download_finished(self):
        self.progress_bar.setValue(100)
    
    def on_download_error(self, error_message):
        self.status_label.setText(f"状态: 下载出错 - {error_message}")
    
    def toggle_pause_resume(self):
        if self.download_thread.get_status() == TaskStatus.PAUSED:
            self.download_thread.resume()
            self.task_resumed.emit(self.task_id)
        else:
            self.download_thread.pause()
            self.task_paused.emit(self.task_id)
    
    def cancel_download(self):
        self.download_thread.cancel()
        self.task_canceled.emit(self.task_id)
    
    def format_size(self, size_bytes):
        """将字节数转换为可读的文件大小"""
        if size_bytes == 0:
            return "0 B"
        
        size_names = ("B", "KB", "MB", "GB", "TB")
        i = 0
        while size_bytes >= 1024 and i < len(size_names) - 1:
            size_bytes /= 1024
            i += 1
        
        return f"{size_bytes:.2f} {size_names[i]}"

class DownloadManager:
    def __init__(self, max_concurrent=3):
        self.max_concurrent = max_concurrent
        self.active_tasks = {}  # 活动任务 {task_id: download_thread}
        self.waiting_tasks = {}  # 等待中的任务
        self.completed_tasks = {}  # 已完成的任务
    
    def add_task(self, download_thread, video_info):
        task_id = str(uuid.uuid4())
        
        # 检查是否可以立即开始下载
        if len(self.active_tasks) < self.max_concurrent:
            self.active_tasks[task_id] = (download_thread, video_info)
            download_thread.start()
        else:
            self.waiting_tasks[task_id] = (download_thread, video_info)
        
        return task_id
    
    def remove_task(self, task_id):
        """从管理器中移除任务"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks.pop(task_id)
            self._check_waiting_tasks()
            return True
        
        if task_id in self.waiting_tasks:
            self.waiting_tasks.pop(task_id)
            return True
        
        return False
    
    def pause_task(self, task_id):
        """暂停任务"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks[task_id]
            thread.pause()
            return True
        
        return False
    
    def resume_task(self, task_id):
        """恢复任务"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks[task_id]
            thread.resume()
            return True
        
        return False
    
    def cancel_task(self, task_id):
        """取消任务"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks[task_id]
            thread.cancel()
            # 不立即从active_tasks移除，等待线程正确退出
            return True
        
        if task_id in self.waiting_tasks:
            # 等待中的任务可以直接移除
            self.waiting_tasks.pop(task_id)
            return True
        
        return False
    
    def on_task_finished(self, task_id):
        """任务完成时的处理"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks.pop(task_id)
            self.completed_tasks[task_id] = (thread, info)
            self._check_waiting_tasks()
    
    def on_task_canceled(self, task_id):
        """任务取消时的处理"""
        if task_id in self.active_tasks:
            thread, info = self.active_tasks.pop(task_id)
            self._check_waiting_tasks()
    
    def _check_waiting_tasks(self):
        """检查等待队列，启动下一个任务"""
        if self.waiting_tasks and len(self.active_tasks) < self.max_concurrent:
            # 获取等待时间最长的任务
            task_id = next(iter(self.waiting_tasks))
            thread, info = self.waiting_tasks.pop(task_id)
            
            self.active_tasks[task_id] = (thread, info)
            thread.start()

class YouTubeDownloader(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('YouTube视频下载器')
        self.setMinimumSize(800, 600)
        
        # 获取系统下载文件夹路径
        self.default_download_path = self._get_system_downloads_folder()
        
        # 设置窗口样式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QLineEdit {
                padding: 8px;
                border: 1px solid #ddd;
                border-radius: 4px;
                background-color: white;
            }
            QPushButton {
                padding: 8px 16px;
                background-color: #2196F3;
                color: white;
                border: none;
                border-radius: 4px;
                min-width: 100px;
            }
            QPushButton:hover {
                background-color: #1976D2;
            }
            QPushButton:disabled {
                background-color: #BDBDBD;
            }
            QLabel {
                color: #333;
            }
            QComboBox {
                padding: 8px;
                border: 1px solid #ddd;
                border-radius: 4px;
                background-color: white;
            }
            QProgressBar {
                border: none;
                background-color: #E0E0E0;
                border-radius: 4px;
                text-align: center;
            }
            QProgressBar::chunk {
                background-color: #2196F3;
                border-radius: 4px;
            }
            QTabWidget::pane {
                border: none;
                background-color: #f5f5f5;
            }
            QTabBar::tab {
                background-color: #e0e0e0;
                border-top-left-radius: 4px;
                border-top-right-radius: 4px;
                padding: 8px 16px;
                margin-right: 2px;
            }
            QTabBar::tab:selected {
                background-color: white;
            }
            QTabBar::tab:hover {
                background-color: #e8e8e8;
            }
        """)
        
        # 创建主窗口部件
        main_widget = QWidget()
        self.setCentralWidget(main_widget)
        layout = QVBoxLayout(main_widget)
        layout.setSpacing(15)
        layout.setContentsMargins(20, 20, 20, 20)

        # URL输入区域
        url_frame = QFrame()
        url_frame.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                padding: 10px;
            }
        """)
        url_layout = QHBoxLayout(url_frame)
        url_layout.setContentsMargins(10, 10, 10, 10)
        
        self.url_input = QLineEdit()
        self.url_input.setPlaceholderText('请输入YouTube视频URL')
        url_layout.addWidget(self.url_input)
        self.fetch_btn = QPushButton('获取视频信息')
        self.fetch_btn.clicked.connect(self.fetch_video_info)
        url_layout.addWidget(self.fetch_btn)
        layout.addWidget(url_frame)

        # 加载进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        self.progress_bar.setRange(0, 0)
        self.progress_bar.setFixedHeight(4)
        layout.addWidget(self.progress_bar)

        # 创建Tab页
        self.tab_widget = QTabWidget()
        self.tab_widget.setStyleSheet("""
            QTabWidget::pane {
                border: none;
                background-color: transparent;
            }
        """)
        layout.addWidget(self.tab_widget)
        
        # 下载Tab
        self.download_tab = QWidget()
        download_layout = QVBoxLayout(self.download_tab)
        download_layout.setContentsMargins(0, 10, 0, 0)
        
        # 视频信息显示区域
        info_frame = QFrame()
        info_frame.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                padding: 15px;
            }
        """)
        info_layout = QVBoxLayout(info_frame)
        info_layout.setContentsMargins(15, 15, 15, 15)
        info_layout.setSpacing(10)

        # 视频内容区域（缩略图和标题水平排列）
        content_container = QFrame()
        content_container.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 4px;
            }
        """)
        content_layout = QHBoxLayout(content_container)
        content_layout.setContentsMargins(4, 4, 4, 4)
        content_layout.setSpacing(8)

        # 缩略图区域
        thumbnail_container = QFrame()
        thumbnail_container.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 0px;
            }
        """)
        thumbnail_layout = QVBoxLayout(thumbnail_container)
        thumbnail_layout.setContentsMargins(0, 0, 0, 0)
        
        self.thumbnail_label = QLabel()
        self.thumbnail_label.setAlignment(Qt.AlignCenter)
        self.thumbnail_label.setMinimumSize(240, 135)
        self.thumbnail_label.setStyleSheet("""
            QLabel {
                border: 1px solid #ddd;
                border-radius: 8px;
                background-color: #f0f0f0;
            }
        """)
        # 设置占位图片
        placeholder_pixmap = QPixmap(240, 135)
        placeholder_pixmap.fill(QColor("#f0f0f0"))
        self.thumbnail_label.setPixmap(placeholder_pixmap)
        # 添加占位文字
        self.thumbnail_placeholder = QLabel("等待解析视频...")
        self.thumbnail_placeholder.setStyleSheet("""
            QLabel {
                color: #999;
                font-size: 13px;
                font-weight: bold;
            }
        """)
        self.thumbnail_placeholder.setAlignment(Qt.AlignCenter)
        self.thumbnail_placeholder.setParent(self.thumbnail_label)
        self.thumbnail_placeholder.setGeometry(0, 0, 240, 135)
        thumbnail_layout.addWidget(self.thumbnail_label)
        content_layout.addWidget(thumbnail_container, 3)

        # 视频标题（右侧）
        title_container = QFrame()
        title_container.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 6px;
            }
        """)
        title_layout = QVBoxLayout(title_container)
        title_layout.setContentsMargins(6, 6, 6, 6)
        title_layout.setSpacing(4)
        
        # 视频标题
        self.title_label = QLabel('等待解析视频...')
        self.title_label.setStyleSheet("""
            QLabel {
                font-size: 15px;
                font-weight: bold;
                color: #999;
                margin-bottom: 4px;
            }
        """)
        self.title_label.setWordWrap(True)
        title_layout.addWidget(self.title_label)

        # 视频信息网格
        info_grid = QFrame()
        info_grid.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 6px;
            }
        """)
        grid_layout = QVBoxLayout(info_grid)
        grid_layout.setContentsMargins(6, 6, 6, 6)
        grid_layout.setSpacing(4)

        # 频道信息
        channel_container = QHBoxLayout()
        channel_label = QLabel('频道:')
        channel_label.setStyleSheet("font-weight: bold; color: #666; font-size: 13px;")
        self.channel_name = QLabel('等待解析...')
        self.channel_name.setStyleSheet("color: #333; font-size: 13px;")
        channel_container.addWidget(channel_label)
        channel_container.addWidget(self.channel_name)
        grid_layout.addLayout(channel_container)

        title_layout.addWidget(info_grid)
        content_layout.addWidget(title_container, 7)

        info_layout.addWidget(content_container)

        # 清晰度选择
        quality_container = QFrame()
        quality_container.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 4px;
            }
        """)
        quality_layout = QHBoxLayout(quality_container)
        quality_layout.setContentsMargins(6, 4, 6, 4)
        
        quality_label = QLabel('选择清晰度:')
        quality_label.setStyleSheet("font-weight: bold; font-size: 13px;")
        quality_layout.addWidget(quality_label)
        self.quality_combo = QComboBox()
        self.quality_combo.setStyleSheet("""
            QComboBox {
                padding: 4px;
                border: 1px solid #ddd;
                border-radius: 4px;
                background-color: white;
                min-height: 24px;
            }
        """)
        quality_layout.addWidget(self.quality_combo)
        info_layout.addWidget(quality_container)

        # 保存路径选择
        path_container = QFrame()
        path_container.setStyleSheet("""
            QFrame {
                background-color: #f8f8f8;
                border-radius: 4px;
                padding: 8px;
            }
        """)
        path_layout = QHBoxLayout(path_container)
        path_layout.setContentsMargins(8, 8, 8, 8)
        
        self.path_input = QLineEdit()
        # 设置默认保存路径为系统下载文件夹
        self.path_input.setText(self.default_download_path)
        self.path_input.setPlaceholderText('选择保存路径')
        path_layout.addWidget(self.path_input)
        self.browse_btn = QPushButton('浏览')
        self.browse_btn.clicked.connect(self.browse_path)
        path_layout.addWidget(self.browse_btn)
        info_layout.addWidget(path_container)

        # 下载按钮
        self.download_btn = QPushButton('开始下载')
        self.download_btn.clicked.connect(self.start_download)
        self.download_btn.setEnabled(False)
        self.download_btn.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                font-weight: bold;
            }
            QPushButton:hover {
                background-color: #388E3C;
            }
        """)
        info_layout.addWidget(self.download_btn)

        # 状态显示
        self.status_label = QLabel('')
        self.status_label.setStyleSheet("""
            QLabel {
                color: #666;
                font-size: 12px;
            }
        """)
        info_layout.addWidget(self.status_label)

        download_layout.addWidget(info_frame)
        
        # 任务管理Tab
        self.tasks_tab = QWidget()
        tasks_layout = QVBoxLayout(self.tasks_tab)
        tasks_layout.setContentsMargins(0, 10, 0, 0)
        
        # 添加顶部状态栏
        status_bar = QFrame()
        status_bar.setStyleSheet("""
            QFrame {
                background-color: white;
                border-radius: 8px;
                margin-bottom: 10px;
                padding: 10px;
            }
        """)
        status_layout = QHBoxLayout(status_bar)
        status_layout.setContentsMargins(10, 10, 10, 10)
        
        # 添加图标和标题
        title_label = QLabel("下载任务管理")
        title_label.setStyleSheet("font-size: 14px; font-weight: bold;")
        status_layout.addWidget(title_label)
        
        status_layout.addStretch(1)
        
        # 添加当前状态信息
        self.active_tasks_label = QLabel("活动任务: 0/3")
        self.active_tasks_label.setStyleSheet("""
            color: #666;
            font-size: 12px;
            background-color: #f0f0f0;
            padding: 5px 10px;
            border-radius: 4px;
        """)
        status_layout.addWidget(self.active_tasks_label)
        
        tasks_layout.addWidget(status_bar)
        
        # 创建滚动区域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setFrameShape(QFrame.NoFrame)
        scroll_area.setStyleSheet("""
            QScrollArea {
                background-color: transparent;
                border: none;
            }
        """)
        
        # 任务列表容器
        self.tasks_container = QWidget()
        self.tasks_container.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.tasks_container.setStyleSheet("background-color: transparent;")
        
        self.tasks_layout = QVBoxLayout(self.tasks_container)
        self.tasks_layout.setContentsMargins(0, 0, 0, 0)
        self.tasks_layout.setSpacing(10)
        
        # 添加空状态提示
        self.empty_tasks_label = QLabel("暂无下载任务")
        self.empty_tasks_label.setAlignment(Qt.AlignCenter)
        self.empty_tasks_label.setStyleSheet("""
            QLabel {
                color: #999;
                font-size: 16px;
                font-weight: bold;
                margin: 30px;
            }
        """)
        self.tasks_layout.addWidget(self.empty_tasks_label)
        
        self.tasks_layout.addStretch(1)  # 让任务项往上靠
        
        scroll_area.setWidget(self.tasks_container)
        tasks_layout.addWidget(scroll_area)
        
        # 添加操作提示信息
        tips_label = QLabel("在视频下载标签页中添加新的下载任务后，将在此处显示")
        tips_label.setAlignment(Qt.AlignCenter)
        tips_label.setStyleSheet("""
            QLabel {
                color: #666;
                font-size: 13px;
                margin-bottom: 10px;
            }
        """)
        tasks_layout.addWidget(tips_label)
        
        # 添加Tab页
        self.tab_widget.addTab(self.download_tab, "视频下载")
        self.tab_widget.addTab(self.tasks_tab, "下载管理")
        
        # 初始化变量
        self.video_info = None
        self.fetch_thread = None
        
        # 初始化下载管理器
        self.download_manager = DownloadManager(max_concurrent=3)
        self.task_items = {}  # 任务ID到UI项的映射
        
    def _get_system_downloads_folder(self):
        """获取系统的下载文件夹路径"""
        if sys.platform == 'win32':
            # Windows
            import winreg
            try:
                with winreg.OpenKey(winreg.HKEY_CURRENT_USER, 
                                 r'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders') as key:
                    return winreg.QueryValueEx(key, '{374DE290-123F-4565-9164-39C4925E467B}')[0]
            except:
                return os.path.join(os.path.expanduser('~'), 'Downloads')
        elif sys.platform == 'darwin':
            # macOS
            return os.path.join(os.path.expanduser('~'), 'Downloads')
        else:
            # Linux/Unix
            download_dir = os.path.join(os.path.expanduser('~'), 'Downloads')
            if os.path.exists(download_dir):
                return download_dir
            else:
                return os.path.expanduser('~')  # 如果Downloads不存在，返回用户主目录

    def fetch_video_info(self):
        url = self.url_input.text().strip()
        if not url:
            QMessageBox.warning(self, '警告', '请输入视频URL')
            return

        # 禁用输入和按钮
        self.url_input.setEnabled(False)
        self.fetch_btn.setEnabled(False)
        # 不显示进度条
        # self.progress_bar.setVisible(True)
        self.status_label.setText('正在获取视频信息...')

        # 创建并启动获取信息的线程
        self.fetch_thread = FetchInfoThread(url)
        self.fetch_thread.finished.connect(self.on_fetch_finished)
        self.fetch_thread.error.connect(self.on_fetch_error)
        self.fetch_thread.progress.connect(self.update_status)
        self.fetch_thread.thumbnail_ready.connect(self.update_thumbnail)
        self.fetch_thread.start()

    def on_fetch_finished(self, info):
        self.video_info = info
        
        # 显示视频标题
        self.title_label.setText(info["title"])
        self.title_label.setStyleSheet("""
            QLabel {
                font-size: 15px;
                font-weight: bold;
                color: #333;
                margin-bottom: 4px;
            }
        """)
        
        # 显示频道信息
        channel = info.get('channel', '未知频道')
        self.channel_name.setText(channel)
        
        # 更新清晰度选项
        self.quality_combo.clear()
        formats = info.get('formats', [])
        for f in formats:
            if f.get('format_note') and f.get('ext'):
                self.quality_combo.addItem(
                    f"{f['format_note']} ({f['ext']})",
                    f"{f['format_id']}"
                )
        
        # 恢复界面状态
        self.url_input.setEnabled(True)
        self.fetch_btn.setEnabled(True)
        # self.progress_bar.setVisible(False)
        self.download_btn.setEnabled(True)
        self.status_label.setText('视频信息获取成功')

    def on_fetch_error(self, error_message):
        # 恢复界面状态
        self.url_input.setEnabled(True)
        self.fetch_btn.setEnabled(True)
        # self.progress_bar.setVisible(False)
        self.status_label.setText('获取视频信息失败')
        
        # 重置所有信息显示
        self.title_label.setText('等待解析视频...')
        self.title_label.setStyleSheet("""
            QLabel {
                font-size: 15px;
                font-weight: bold;
                color: #999;
                margin-bottom: 4px;
            }
        """)
        self.channel_name.setText('等待解析...')
        
        # 重置缩略图
        placeholder_pixmap = QPixmap(240, 135)
        placeholder_pixmap.fill(QColor("#f0f0f0"))
        self.thumbnail_label.setPixmap(placeholder_pixmap)
        self.thumbnail_placeholder.show()
        
        QMessageBox.critical(self, '错误', f'获取视频信息失败: {error_message}')

    def update_status(self, message):
        self.status_label.setText(message)

    def update_thumbnail(self, pixmap):
        self.thumbnail_label.setPixmap(pixmap)
        self.thumbnail_placeholder.hide()

    def browse_path(self):
        # 使用当前设置的路径或默认下载路径作为起始目录
        start_path = self.path_input.text() or self.default_download_path
        folder = QFileDialog.getExistingDirectory(self, '选择保存路径', start_path)
        if folder:
            self.path_input.setText(folder)

    def start_download(self):
        if not self.video_info:
            QMessageBox.warning(self, '警告', '请先获取视频信息')
            return

        save_path = self.path_input.text().strip()
        if not save_path:
            QMessageBox.warning(self, '警告', '请选择保存路径')
            return

        format_id = self.quality_combo.currentData()
        if not format_id:
            QMessageBox.warning(self, '警告', '请选择视频清晰度')
            return

        # 显示加载状态
        self.download_btn.setEnabled(False)
        # 下载任务准备时显示进度条
        self.progress_bar.setVisible(True)
        self.status_label.setText('准备下载任务...')
        
        # 使用任务创建线程异步创建下载任务
        self.task_creation_thread = TaskCreationThread(
            self.url_input.text(),
            format_id,
            save_path,
            self.video_info,
            self.download_manager
        )
        
        # 连接信号
        self.task_creation_thread.task_created.connect(self.on_task_created)
        
        # 启动线程
        self.task_creation_thread.start()
        
        # 切换到任务管理Tab
        self.tab_widget.setCurrentIndex(1)
        
        # 重置界面以便添加新任务
        self.reset_download_form()
    
    def on_task_created(self, task_id, download_thread, task_item):
        """当任务创建完成后的处理"""
        # 连接任务控制信号
        task_item.task_paused.connect(lambda tid: self.download_manager.pause_task(tid))
        task_item.task_resumed.connect(lambda tid: self.download_manager.resume_task(tid))
        task_item.task_canceled.connect(lambda tid: self.download_manager.cancel_task(tid))
        
        # 连接下载完成和取消信号
        download_thread.finished.connect(lambda: self.download_manager.on_task_finished(task_id))
        download_thread.status_changed.connect(lambda status: self._on_task_status_changed(task_id, status))
        
        # 将任务项添加到任务面板
        self.tasks_layout.insertWidget(0, task_item)
        self.task_items[task_id] = task_item
        
        # 隐藏空状态提示
        self.empty_tasks_label.setVisible(False)
        
        # 更新活动任务数量显示
        self._update_active_tasks_count()
        
        # 任务创建完成后，隐藏进度条
        self.progress_bar.setVisible(False)

    def _on_task_status_changed(self, task_id, status):
        if status in [TaskStatus.COMPLETED, TaskStatus.CANCELED, TaskStatus.ERROR]:
            if status == TaskStatus.CANCELED:
                self.download_manager.on_task_canceled(task_id)
                
            # 任务完成或取消后，可以延迟从UI中移除
            if task_id in self.task_items:
                # 获取当前任务项
                task_item = self.task_items[task_id]
                
                # 更改任务项的样式以表示完成或取消
                if status == TaskStatus.COMPLETED:
                    task_item.setStyleSheet(task_item.styleSheet() + """
                        QFrame {
                            background-color: #E8F5E9;
                            border: 1px solid #A5D6A7;
                        }
                    """)
                elif status == TaskStatus.CANCELED:
                    task_item.setStyleSheet(task_item.styleSheet() + """
                        QFrame {
                            background-color: #FFEBEE;
                            border: 1px solid #FFCDD2;
                        }
                    """)
                elif status == TaskStatus.ERROR:
                    task_item.setStyleSheet(task_item.styleSheet() + """
                        QFrame {
                            background-color: #FFF3E0;
                            border: 1px solid #FFCCBC;
                        }
                    """)
            
            # 检查是否所有任务都已经完成
            active_tasks_count = len([t for t in self.task_items.values() 
                                    if t.download_thread.get_status() in 
                                    [TaskStatus.DOWNLOADING, TaskStatus.PAUSED, TaskStatus.WAITING]])
            
            # 如果没有活动任务，检查是否要显示空状态
            if active_tasks_count == 0 and len(self.task_items) == 0:
                self.empty_tasks_label.setVisible(True)
                
            # 更新活动任务数量
            self._update_active_tasks_count()
        else:
            # 状态变化时也更新活动任务数量
            self._update_active_tasks_count()
            
    def _update_active_tasks_count(self):
        """更新活动任务数量显示"""
        active_count = len(self.download_manager.active_tasks)
        waiting_count = len(self.download_manager.waiting_tasks)
        max_count = self.download_manager.max_concurrent
        
        if waiting_count > 0:
            self.active_tasks_label.setText(f"活动任务: {active_count}/{max_count} (等待中: {waiting_count})")
        else:
            self.active_tasks_label.setText(f"活动任务: {active_count}/{max_count}")

    def reset_download_form(self):
        # 清空输入框
        self.url_input.clear()
        
        # 重置视频信息
        self.video_info = None
        
        # 重置界面元素
        self.title_label.setText('等待解析视频...')
        self.title_label.setStyleSheet("""
            QLabel {
                font-size: 15px;
                font-weight: bold;
                color: #999;
                margin-bottom: 4px;
            }
        """)
        self.channel_name.setText('等待解析...')
        
        # 重置缩略图
        placeholder_pixmap = QPixmap(240, 135)
        placeholder_pixmap.fill(QColor("#f0f0f0"))
        self.thumbnail_label.setPixmap(placeholder_pixmap)
        self.thumbnail_placeholder.show()
        
        # 清空清晰度下拉框
        self.quality_combo.clear()
        
        # 禁用下载按钮
        self.download_btn.setEnabled(False)
        
        # 确保进度条隐藏
        self.progress_bar.setVisible(False)
        
        # 清空状态标签
        self.status_label.setText('')
        
        # 注意：我们不重置保存路径输入框，保持当前路径设置

    def update_progress(self, message, percentage, downloaded_bytes):
        self.status_label.setText(message)

    def download_finished(self):
        self.download_btn.setEnabled(True)
        self.status_label.setText('下载完成！')
        QMessageBox.information(self, '完成', '视频下载完成！')

    def download_error(self, error_message):
        self.download_btn.setEnabled(True)
        self.status_label.setText('下载失败')
        QMessageBox.critical(self, '错误', f'下载失败: {error_message}')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = YouTubeDownloader()
    window.show()
    sys.exit(app.exec()) 